import browser from "./browser";
import domUtils from "./domUtils";
import Range from "./Range";
export default class Selection {
    document;
    constructor(doc) {
        this.document = doc;
    }
    

    getNative() {
        var doc = this.document;
        try {
            return !doc
                ? null
                : browser.ie9below
                    ? doc.selection
                    : domUtils.getWindow(doc).getSelection();
        } catch (e) {
            return null;
        }
    }

    getRange() {       
        var me = this;
        function optimze(range) {
            var child = me.document.body.firstChild,
                collapsed = range.collapsed;
            while (child && child.firstChild) {
                range.setStart(child, 0);
                child = child.firstChild;
            }
            if (!range.startContainer) {
                range.setStart(me.document.body, 0);
            }
            if (collapsed) {
                range.collapse(true);
            }
        }
        
        var range = new Range(this.document);

        if (browser.ie9below) {
            var nativeRange = me.getIERange();
            if (nativeRange) {
                //备份的_bakIERange可能已经实效了，dom树发生了变化比如从源码模式切回来，所以try一下，实效就放到body开始位置
                try {
                    transformIERangeToRange(nativeRange, range);
                } catch (e) {
                    optimze(range);
                }
            } else {
                optimze(range);
            }
        } else {
            var sel = me.getNative();
            if (sel && sel.rangeCount) {
                var firstRange = sel.getRangeAt(0);
                var lastRange = sel.getRangeAt(sel.rangeCount - 1);
                range
                    .setStart(firstRange.startContainer, firstRange.startOffset)
                    .setEnd(lastRange.endContainer, lastRange.endOffset);
                if (
                    range.collapsed &&
                    domUtils.isBody(range.startContainer) &&
                    !range.startOffset
                ) {
                    optimze(range);
                }
            } else {
                //trace:1734 有可能已经不在dom树上了，标识的节点
                if (
                    this._bakRange &&
                    domUtils.inDoc(this._bakRange.startContainer, this.document)
                ) {
                    return this._bakRange;
                }
                optimze(range);
            }
        }
        return (this._bakRange = range);
    }


     /**
         * 获取开始元素，用于状态反射
         * @method getStart
         * @return { Element } 获得开始元素
         * @example
         * ```javascript
         * editor.selection.getStart();
         * ```
         */
     getStart() {
        if (this._cachedStartElement) {
          return this._cachedStartElement;
        }
        var range = browser.ie9below ? this.getIERange() : this.getRange(),
          tmpRange,
          start,
          tmp,
          parent;
        if (browser.ie9below) {
          if (!range) {
            //todo 给第一个值可能会有问题
            return this.document.body.firstChild;
          }
          //control元素
          if (range.item) {
            return range.item(0);
          }
          tmpRange = range.duplicate();
          //修正ie下<b>x</b>[xx] 闭合后 <b>x|</b>xx
          tmpRange.text.length > 0 && tmpRange.moveStart("character", 1);
          tmpRange.collapse(1);
          start = tmpRange.parentElement();
          parent = tmp = range.parentElement();
          while ((tmp = tmp.parentNode)) {
            if (tmp == start) {
              start = parent;
              break;
            }
          }
        } else {
          range.shrinkBoundary();
          start = range.startContainer;
          if (start.nodeType == 1 && start.hasChildNodes()) {
            start =
              start.childNodes[
                Math.min(start.childNodes.length - 1, range.startOffset)
              ];
          }
          if (start.nodeType == 3) {
            return start.parentNode;
          }
        }
        return start;
      }


    /**
         * 获取选区开始位置的父节点到body
         * @method getStartElementPath
         * @return { Array } 返回父节点集合
         * @example
         * ```javascript
         * editor.selection.getStartElementPath();
         * ```
         */
    getStartElementPath() {      
        var start = this.getStart();
        if (start) {
          return domUtils.findParents(start, true, null, true);
        }
        return [];
      }
}